Vamos a proponernos un desafío, un programa super-simple: queremos mostrar el contenido de un fichero por la pantalla. El programa es este:
#include <fstream> #include <iostream> using namespace std; int main() { ifstream F("fichero.txt"); string linea; while (!F.eof()) { getline(F, linea); cout << linea << endl; } }
Para que funcione, de todas maneras, el fichero.txt tiene que existir. Si no, el programa se parará esperando leer una línea. Eso se puede arreglar:
#include <fstream> #include <iostream> using namespace std; int main() { ifstream F("fichero.txt"); if (!F.is_open()) { cout << "No se ha podido abrir el fichero" << endl; } else { string linea; while (!F.eof()) { getline(F, linea); cout << linea << endl; } } }
Utilizando el método is_open, podemos preguntar al objeto F si se ha podido abrir el fichero realmente y actuar de acorde con ello.
De todas maneras, el programa es un poco incómodo. Cada vez que quiero mostrar un fichero distinto, tengo que cambiar el nombre que hay en el código y recompilar. No se puede hacer mejor?
La idea, de hecho es pedir el nombre al usuario, así:
string nombre_fichero; cin >> nombre_fichero;
Y luego simplemente abrir un fichero con ese nombre:
ifstream F(nombre_fichero);
Si pruebas esto, de todas maneras, verás que no funciona. El error que se produce es de compilación y es un poco ilógico. El problema radica en que al crear el objeto F se pasa un parámetro de tipo string y en realidad se debería pasar un parámetro de tipo char * (puntero a caracteres).
El tipo char * es el de las "cadenas de caracteres" de C, el lenguaje que precede a C++. Lo que sucede entonces es que tenemos un nombre_fichero de tipo string (correspondiente a C++) y luego un método de la clase ifstream nos pide una variable de tipo char *. Esto parece ilógico y es, de hecho, un error en la librería estándar.
Pero hay una manera de arreglarlo, que hay que conocer. Existe un método string::c_str que tiene la siguiente declaración:
char * string::c_str();
Es decir, a partir de un string devuelve un char*, que es el tipo que necesitamos. En realidad convierte un string "moderno" a los "strings" o "cadenas de caracteres" antiguos.
Entonces, la manera de abrir el fichero seria:
ifstream F(nombre_fichero.c_str());
Es importante ver que el método c_str no lleva parámetros pero al invocarlo, tal como con las acciones o funciones, se ponen los paréntesis de abrir y cerrar de todas formas.
Una vez enterados de este importante pequeño detalle, podemos acabar el programa:
#include <fstream> #include <iostream> using namespace std; int main() { string nombre_fichero; cout << "Fichero? "; cin >> nombre_fichero; ifstream F(nombre_fichero.c_str()); if (!F.is_open()) { cout << "No se ha podido abrir el fichero" << endl; } else { string linea; while (!F.eof()) { getline(F, linea); cout << linea << endl; } } }
En preparación